package com.borqsprocessmanager.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import android.database.Cursor;
import android.os.AsyncTask;
import android.util.Log;

import com.borqsprocessmanager.App;
import com.borqsprocessmanager.BatteryManagerService;
import com.borqsprocessmanager.db.DBProvider.ProcessTable;
import com.borqsprocessmanager.info.ProcessStatsInfo;

public class DBAsyncWorker extends
        AsyncTask<Integer, Object, ArrayList<ProcessStatsInfo>> {
    private final String TAG = "DBAsyncWorker";

    private static boolean isWorking = false;
    private IShowSampleRes mShowSampleRes = null;

    public DBAsyncWorker(IShowSampleRes showSampleRes) {
        this.mShowSampleRes = showSampleRes;
    }

    @Override
    protected ArrayList<ProcessStatsInfo> doInBackground(Integer... sampleId) {
        if (!isWorking) {
            isWorking = true;
            ArrayList<ProcessStatsInfo> resList = getDataForDB(sampleId[0]);
            Log.v(TAG, "resList.size()" + resList.size());
            Collections.sort(resList);
            return resList;
        }
        return null;
    }

    @Override
    protected void onPostExecute(ArrayList<ProcessStatsInfo> result) {
        if (isWorking && result != null && result.size() > 0) {
            Log.v(TAG, "result != null && result.size() > 0" + result.size());
            isWorking = false;
            mShowSampleRes.showSampleRes(result);
        }
        mShowSampleRes = null;
    }

    private ArrayList<ProcessStatsInfo> getDataForDB(int sampleId) {
        com.borqsprocessmanager.util.Log.v(TAG, "getDataForDB_sampleId==="
                + sampleId);
        ArrayList<ProcessStatsInfo> resList = new ArrayList<ProcessStatsInfo>();
        Cursor cursor = App.mContext.getContentResolver().query(
                ProcessTable.CONTENT_URI, null, ProcessTable.SAMPLE_ID + "=?",
                new String[] { (sampleId) + "" }, null);
        com.borqsprocessmanager.util.Log.v(TAG, "getDataForDB_cursor==="
                + cursor.getCount());
        if (null != cursor && cursor.getCount() > 0) {
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor
                    .moveToNext()) {
                ProcessStatsInfo info = new ProcessStatsInfo();
                info.setSampleId(cursor.getInt(cursor
                        .getColumnIndex(ProcessTable.SAMPLE_ID)));
                info.setAppName(cursor.getString(cursor
                        .getColumnIndex(ProcessTable.APPNAME_NAME)));
                info.setPackageName(cursor.getString(cursor
                        .getColumnIndex(ProcessTable.PKG_NAME)));
                info.setProcessName(cursor.getString(cursor
                        .getColumnIndex(ProcessTable.PROCESS_NAME)));
                info.setType(cursor.getInt(cursor
                        .getColumnIndex(ProcessTable.TYPE)));
                info.setRatio(cursor.getDouble(cursor
                        .getColumnIndex(ProcessTable.RATIO)));
                info.setTotal(cursor.getLong(cursor
                        .getColumnIndex(ProcessTable.TOTAL_BYTES)));
                info.setRx(cursor.getLong(cursor
                        .getColumnIndex(ProcessTable.RX_BYTES)));
                info.setTx(cursor.getLong(cursor
                        .getColumnIndex(ProcessTable.TX_BYTES)));
                if (info.type < 5) {
                    if (info.total > 0) {
                        info.type += 1;
                    } else if (info.ratio > 0) {
                        info.type += 2;
                    }
                }
                resList.add(info);
                Log.v(TAG, "moveToFirst_AppName=" + info.processName);
            }
            cursor.close();
            Log.v(TAG, "getDataForDB_resList.size===" + resList.size());
            resList = analysisOfData(resList);
            Log.v(TAG, "analysisOfData_resList.size===" + resList.size());
        }
        cursor = null;
        return resList;
    }

    private ArrayList<ProcessStatsInfo> analysisOfData(
            ArrayList<ProcessStatsInfo> list) {
        HashMap<String, ProcessStatsInfo> map = new HashMap<String, ProcessStatsInfo>();
        HashMap<String, Integer> countMap = new HashMap<String, Integer>();
        int listSize = list.size();
        for (int i = 0; i < listSize; i++) {
            ProcessStatsInfo info = list.get(i);
            com.borqsprocessmanager.util.Log.v(TAG,
                    "analysisOfData_info.app.name" + info.processName);
            if (map.containsKey(info.packageName)) {
                ProcessStatsInfo mapInfo = map.get(info.packageName);
                mapInfo.total += info.total;
                mapInfo.tx += info.tx;
                mapInfo.rx += info.rx;
                info.ratio += mapInfo.ratio;
                int mapType = mapInfo.type;
                int type = info.type;
                if (type == 2 && type == mapType) {
                    Integer count = countMap.get(info.packageName);
                    if (count == null) {
                        count = 0;
                    }
                    countMap.put(info.packageName, count + 1);
                }
                if (type != mapType) {
                    mapInfo.type = 3;
                }
            } else {
                map.put(info.packageName, info);
                com.borqsprocessmanager.util.Log.v(TAG, "analysisOfData_put==="
                        + info.processName);
            }
        }
        com.borqsprocessmanager.util.Log.v(TAG,
                "analysisOfData_map===" + map.size());
        return getMapData(map, countMap);
    }

    public ArrayList<ProcessStatsInfo> getMapData(
            HashMap<String, ProcessStatsInfo> map,
            HashMap<String, Integer> countMap) {
        ArrayList<ProcessStatsInfo> resList = new ArrayList<ProcessStatsInfo>();
        Iterator<Entry<String, ProcessStatsInfo>> iter = map.entrySet()
                .iterator();
        Iterator<Entry<String, Integer>> iterConut = countMap.entrySet()
                .iterator();
        Log.v(TAG, "countMap.size===" + countMap.size());
        while (iterConut.hasNext()) {
            Map.Entry entry = (Map.Entry) iterConut.next();
            String key = (String) entry.getKey();
            Log.v(TAG, "key===" + key);
            int count = (Integer) entry.getValue();
            Log.v(TAG, "getValue===" + entry.getValue());
            map.get(key).ratio /= count;
        }

        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            ProcessStatsInfo info = (ProcessStatsInfo) entry.getValue();
            resList.add(info);
        }
        return resList;
    }

}
